/* ---------------------------------------------- 头文件包含 ---------------------------------------------- */
#include "./SYSTEM/SYS/sys.h"
#include "./SYSTEM/Task/task_manager.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/REMOTE/bsp_remote.h"
#include "./BSP/USART/bsp_usart.h"
#include "./BSP/24CXX/bsp_24cxx.h"
#include "./BSP/NORFLASH/bsp_norflash.h"
#include "./USMART/usmart.h"
#include "./MALLOC/malloc.h"
#include "./BSP/SDMMC/spi_sdcard.h"
#include "./FATFS/exfuns/exfuns.h"
#include "./TEXT/text.h"
#include "./TEXT/charset_convert.h"
#include "./SYSTEM/sys_param/sys_param.h"
#include "main_menu.h"
#include "string.h"

/* --------------------------------------------- 日志标签定义 --------------------------------------------- */

/* SYS模块专用日志标签 */
#define SYS_LOG_TAG         "SYS"
#define FATFS_LOG_TAG       "FATFS"
#include "elog.h"

/* -------------------------------------------- 中断向量表控制 -------------------------------------------- */

/**
 * @brief       设置中断向量表偏移地址
 * @param       baseaddr: 基址
 * @param       offset: 偏移量
 * @retval      无
 */
void sys_nvic_set_vector_table(uint32_t baseaddr, uint32_t offset)
{
    /* 设置NVIC的向量表偏移寄存器,VTOR低9位保留,即[8:0]保留 */
    SCB->VTOR = baseaddr | (offset & (uint32_t)0xFFFFFE00);
}

/* -------------------------------------------- 低功耗控制函数 -------------------------------------------- */

/**
 * @brief       执行WFI指令(执行完该指令进入低功耗状态, 等待中断唤醒)
 * @param       无
 * @retval      无
 */
void sys_wfi_set(void)
{
    __ASM volatile("wfi");
}

/**
 * @brief       进入待机模式
 * @param       无
 * @retval      无
 */
void sys_standby(void)
{
    __HAL_RCC_PWR_CLK_ENABLE();    /* 使能电源时钟 */
    SET_BIT(PWR->CR, PWR_CR_PDDS); /* 进入待机模式 */
}

/* -------------------------------------------- 中断控制函数 ---------------------------------------------- */

/**
 * @brief       关闭所有中断(但是不包括fault和NMI中断)
 * @param       无
 * @retval      无
 */
void sys_intx_disable(void)
{
    __ASM volatile("cpsid i");
}

/**
 * @brief       开启所有中断
 * @param       无
 * @retval      无
 */
void sys_intx_enable(void)
{
    __ASM volatile("cpsie i");
}

/* -------------------------------------------- 系统控制函数 ---------------------------------------------- */

/**
 * @brief       设置栈顶地址
 * @note        左侧若出现红X, 属于MDK误报, 实际是没问题的
 * @param       addr: 栈顶地址
 * @retval      无
 */
void sys_msr_msp(uint32_t addr)
{
    __set_MSP(addr);    /* 设置栈顶地址 */
}

/**
 * @brief       系统软复位
 * @param       无
 * @retval      无
 */
void sys_soft_reset(void)
{
    NVIC_SystemReset();
}

/**
 * @brief EasyLogger初始化
 * @details 配置日志系统的格式和级别，包含各种高级功能
 */
static void EasyLoggerInit(void)
{
    /* 初始化 EasyLogger */
    elog_init();
    
    /* ---------------------------------------- 格式化输出配置 ---------------------------------------- */
    /* ASSERT级别：显示所有信息（用于严重错误） */
    elog_set_fmt(ELOG_LVL_ASSERT, ELOG_FMT_ALL);
    
    /* ERROR级别：显示级别、标签、时间、文件、行号 */
    elog_set_fmt(ELOG_LVL_ERROR, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME | ELOG_FMT_DIR | ELOG_FMT_LINE);
    
    /* WARN级别：显示级别、标签、时间 */
    elog_set_fmt(ELOG_LVL_WARN, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
    
    /* INFO级别：显示级别、标签、时间 */
    elog_set_fmt(ELOG_LVL_INFO, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
    
    /* DEBUG级别：显示详细信息但排除函数名和线程信息 */
    elog_set_fmt(ELOG_LVL_DEBUG, ELOG_FMT_ALL & ~(ELOG_FMT_FUNC | ELOG_FMT_T_INFO | ELOG_FMT_P_INFO));
    
    /* VERBOSE级别：显示详细信息但排除函数名和线程信息 */
    elog_set_fmt(ELOG_LVL_VERBOSE, ELOG_FMT_ALL & ~(ELOG_FMT_FUNC | ELOG_FMT_T_INFO | ELOG_FMT_P_INFO));
    
    /* ------------------------------------------ 过滤器配置 ------------------------------------------- */
    /* 设置全局日志级别过滤（只显示INFO及以上级别的日志）*/
    elog_set_filter_lvl(ELOG_LVL_INFO);
    
    /* 设置标签过滤（只显示特定标签的日志）*/
    // elog_set_filter_tag("FLOW_DRV");
    
    /* 设置关键字过滤（只显示包含特定关键字的日志）*/
    // elog_set_filter_kw("error");
    
    /* 为不同标签设置不同的日志级别 */
    // elog_set_filter_tag_lvl("SYS", ELOG_LVL_DEBUG);         /* SYS系统模块显示DEBUG级别 */
    
    /* 完全屏蔽某些模块的日志 */
    // elog_set_filter_tag_lvl("UNWANTED_MODULE", ELOG_FILTER_LVL_SILENT);  /* 完全屏蔽 */
    
    /* 其他过滤选项 */
    // elog_set_filter_lvl(ELOG_LVL_INFO);        /* 全局只显示INFO及以上级别 */
    // elog_set_filter_tag("FLOW_DRV");           /* 只显示FLOW_DRV标签的日志 */
    // elog_set_filter_kw("error");               /* 只显示包含"error"关键字的日志 */
    
    /* ------------------------------------------ 颜色输出配置 ------------------------------------------ */
    /* 启用颜色输出（需要在elog_cfg.h中启用ELOG_COLOR_ENABLE）*/
    // elog_set_text_color_enabled(true);
    
    /* ------------------------------------------- 输出锁配置 ------------------------------------------ */
    /* 禁用输出锁*/
    elog_output_lock_enabled(false);
    
    /* ----------------------------------------- 缓冲输出配置 ------------------------------------------- */
    /* 启用缓冲输出（需要在elog_cfg.h中启用ELOG_BUF_OUTPUT_ENABLE）*/
    // elog_buf_enabled(true);
    
    /* ----------------------------------------- 异步输出配置 ------------------------------------------ */
    /* 启用异步输出（需要在elog_cfg.h中启用ELOG_ASYNC_OUTPUT_ENABLE）*/
    // elog_async_enabled(true);
    
    /* ---------------------------------------- 启动 EasyLogger --------------------------------------- */
    elog_start();
    
    /* ------------------------------------------ 测试日志输出 ------------------------------------------- */
    log_i("EasyLogger初始化完成，当前配置:");
    log_i("- 全局输出级别: %s", "INFO");
    log_i("- 输出锁: %s", "禁用");
    log_i("- 颜色输出: %s", "禁用");
    log_d("这是一条DEBUG级别的测试日志");
    log_w("这是一条WARN级别的测试日志");
    log_e("这是一条ERROR级别的测试日志");
}

/* FATFS/存储管理任务 */
void InitFATFSManager(void)
{
    uint32_t total, free;
    uint8_t res = 0;
    
    elog_info(FATFS_LOG_TAG, "FATFS Manager Initializing...");
    
    exfuns_init();                  /* 为fatfs相关变量申请内存 */
    f_mount(fs[0], "0:", 1);        /* 挂载SD卡 */
    res = f_mount(fs[1], "1:", 1);  /* 挂载FLASH */
    
    if (res == 0X0D)                /* FLASH磁盘,FAT文件系统错误,重新格式化FLASH */
    {
        elog_warn(FATFS_LOG_TAG, "Flash Disk Formatting...");
        res = f_mkfs("1:", 0, 0, FF_MAX_SS);            /* 格式化FLASH,1:,盘符;0,使用默认格式化参数 */

        if (res == 0)
        {
            f_setlabel((const TCHAR *)"1:ALIENTEK");    /* 设置Flash磁盘的名字为：ALIENTEK */
            elog_info(FATFS_LOG_TAG, "Flash Disk Format Finish");
        }
        else
        {
            elog_error(FATFS_LOG_TAG, "Flash Disk Format Error: %d", res);
        }
    }

    /* 尝试获取SD卡容量信息，最多重试3次 */
    uint8_t retry_count = 3;
    while (exfuns_get_free((uint8_t *)"0", &total, &free) && retry_count > 0)
    {
        elog_warn(FATFS_LOG_TAG, "SD Card Fatfs Error! Retrying...(%d)", retry_count);
        retry_count--;
        delay_ms(500);  /* 延时500ms后重试 */
    }

    if (retry_count > 0)
    {
        elog_info(FATFS_LOG_TAG, "FATFS OK!");
        elog_info(FATFS_LOG_TAG, "SD Total Size: %lu MB", (unsigned long)total >> 10);
        elog_info(FATFS_LOG_TAG, "SD Free Size: %lu MB", (unsigned long)free >> 10);
    }
    else
    {
        elog_error(FATFS_LOG_TAG, "SD Card FATFS Failed! Continue without SD card info.");
    }
}

/**
 * @brief FATFS文件系统功能演示
 * @details 演示常用FATFS API的使用方法，验证文件系统是否正常工作
 */
void fatfs_basic_test(void)
{
    printf("\n----------- FATFS 功能演示 -----------\n");
    
    /* 1. 获取磁盘信息 - f_getfree() */
    FATFS *fs_ptr;
    DWORD free_clusters;
    FRESULT res = f_getfree("0:", &free_clusters, &fs_ptr);
    if (res == FR_OK) 
    {
        printf("磁盘空间: 空闲簇数 %lu\n", free_clusters);
    }
    
    /* 2. 目录操作 - f_opendir(), f_readdir(), f_closedir() */
    DIR dir;
    FILINFO fno;
    if (f_opendir(&dir, "0:/") == FR_OK) 
    {
        printf("根目录文件列表:\n");
        int count = 0;
        while (f_readdir(&dir, &fno) == FR_OK && fno.fname[0] != 0 && count < 5) 
        {
            printf("  %s %s\n", fno.fname, (fno.fattrib & AM_DIR) ? "[DIR]" : "");
            count++;
        }
        f_closedir(&dir);
    }
    
    /* 3. 文件操作 - f_open(), f_write(), f_read(), f_close() */
    FIL file;
    const char* test_data = "Hello FATFS!\n";
    UINT bw, br;
    
    /* 写文件 */
    if (f_open(&file, "0:/demo.txt", FA_CREATE_ALWAYS | FA_WRITE) == FR_OK) 
    {
        f_write(&file, test_data, strlen(test_data), &bw);
        f_close(&file);
        printf("写入文件: demo.txt (%d字节)\n", bw);
    }
    
    /* 读文件 */
    if (f_open(&file, "0:/demo.txt", FA_READ) == FR_OK) 
    {
        char buffer[32];
        f_read(&file, buffer, sizeof(buffer)-1, &br);
        buffer[br] = '\0';
        f_close(&file);
        printf("读取内容: %s", buffer);
        
        /* 删除测试文件 */
        f_unlink("0:/demo.txt");
        printf("测试文件已清理\n");
    }
    
    /* 4. 检查系统目录结构 */
    if (f_opendir(&dir, "0:/SYSTEM") == FR_OK) 
    {
        printf("SYSTEM目录: 存在\n");
        f_closedir(&dir);
        
        if (f_opendir(&dir, "0:/SYSTEM/FONT") == FR_OK) 
        {
            printf("FONT目录: 存在\n");
            f_closedir(&dir);
        }
    }
    
    printf("-------------- 演示完成 --------------\n\n");
}

/**
 * @brief 系统外设初始化
 * @details 初始化基础外设和驱动
 */
void SystemPeripheralInit(void)
{
    EasyLoggerInit();               /* EasyLogger初始化 - 必须最先初始化 */
    FML_KEY_Init();                 /* 按键初始化 */
    FML_LED_Init();                 /* LED初始化 */
    delay_init(72);                 /* 延时初始化 */
    usart_init(115200);             /* 串口初始化为115200 */
    iwdg_init(IWDG_PRESCALER_128, 3125);    /* 初始化看门狗，超时时间：Tout = (4 × 32 × 3125) / 40000 = 400000 / 40000 = 10秒 */
    adc_task_init();                /* 初始化ADC任务 */
    rtc_init();                     /* 初始化RTC */
    remote_init();                  /* 红外接收初始化 */
}

/**
 * @brief 系统模块初始化
 * @details 初始化各功能模块
 */
void SystemModuleInit(void)
{
    lcd_init();                             /* 初始化LCD */
    usmart_dev.init(72);                    /* 初始化USMART */
    at24cxx_init();                         /* 初始化24C02 */
    norflash_init();                        /* 初始化Norflash*/
    my_mem_init(SRAMIN);                    /* 初始化内部SRAM内存池 */
    sd_init();                              /* 初始化SD卡*/
//    show_sdcard_info();                     /* 打印SD卡信息 */
    InitFATFSManager();                     /* 初始化FATFS文件系统*/
//    fatfs_basic_test();                     /* FATFS基础功能测试 */
    fonts_manager_init();                   /* 初始化字库 */
//    fonts_test_display_direct();            /* 汉字显示测试 */
//    utf8_to_gbk_test();                     /* UTF8到GBK转换测试 */
    
    InitParam(true);                        /* 初始化参数系统 */
    ShowAllParam();                         /* 显示所有参数 */
    
    MainMenu_Init();                        /* 初始化菜单系统 */
}

/**
 * @brief 系统任务初始化
 * @details 创建和启动系统任务
 */
void SystemTaskInit(void)
{
    cotTask_Init();
    cotTask_Creat(ScanKeyTask, 20, 5);              /* 按键扫描任务，20ms执行一次 */
    cotTask_Creat(ScanLedTask, 20, 6);              /* LED控制任务，20ms执行一次 */
    cotTask_Creat(WatchdogTask, 1000, 5);           /* 喂狗任务，1秒执行一次 */
    cotTask_Creat(ScanRemoteTask, 100, 6);          /* REMOTE扫描任务，100ms执行一次 */
//    cotTask_Creat(ScanADCTask, 200, 6);             /* ADC扫描任务，200ms执行一次 */
//    cotTask_Creat(RTCDisplayTask, 100, 7);          /* RTC时钟显示任务，100ms执行一次 */
//    cotTask_Creat(TestScheduleTask, 1000, 8);       /* 测试调度任务，1秒执行一次 */
    cotTask_Start();
}
